<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML dir=ltr XMLNS:MSHelp = "http://msdn.microsoft.com/mshelp" xmlns:ddue = 
"http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:xlink = 
"http://www.w3.org/1999/xlink" xmlns:tool = "http://www.microsoft.com/tooltip"
XMLNS:[default] http://ddue.schemas.microsoft.com/authoring/2003/5 =
"http://ddue.schemas.microsoft.com/authoring/2003/5"><HEAD>
  <TITLE>Session Messages Sample</TITLE>
  <META content="text/html; CHARSET=utf-8" http-equiv=Content-Type></META>
  <META name=save content=history></META>
  <LINK rel=stylesheet type=text/css
  href="../../../CommonFiles/Classic.css"></LINK>

  <META name=GENERATOR content="MSHTML 8.00.6001.18783">
    <style type="text/css">
      .style1 {
      font-family: monospace;
      font-size: 100%;
      color: #000000;
      }
      .style2 {
      font-family: monospace;
      font-size: small;
      color: #000000;
      }
      </style>
  </HEAD>
<BODY>
  <DIV id=header>
    <TABLE id=topTable width="100%">
      <TBODY>
        <TR id=headerTableRow1>
          <TD align=left>
            <SPAN id=runningHeaderText></SPAN>
          </TD>
        </TR>
        <TR id=headerTableRow2>
          <TD align=left>
              <SPAN id=nsrTitle>Session Messages Sample</SPAN>
          </TD>
        </TR>
        <TR id=headerTableRow3>
          <TD></TD>
        </TR>
      </TBODY>
    </TABLE>
  </DIV>
  <DIV id=mainSection>
    <DIV id=mainBody>
      <P>
          This sample demonstrates how to use the Windows Azure Service Bus and 
          the Messaging Session functionality.
      </P>
      <P>
          The sample shows simple senders and receivers communicating via a Service Bus 
          queue. The SampleManager first prompts for service namespace credentials. These 
          are used to authenticate with the Access Control service, and acquire an access 
          token that proves to the Service Bus infrastructure that the client is 
          authorized to access the queue. The SampleManager creates two queues, one 
          requiring sessions and one that does not, then creates one or more senders and 
          receivers. The sender(s) send messages with a range of SessionId values 
          simulating different orders into the queues, first to the sessionless queue then 
          to the queue requiring sessions. The receivers read orders until the sessionless 
          queue is empty, then receives messages by session.</P>
        <P>
            When messages are being received from the sessionless queue, the receivers will 
            process the messages in the order they appear, regardless of the SessionId. When 
            messages are being received from the session queue, the receivers will only 
            receive messages that have the same SessionId until there are no more remaining, 
            then will begin receiving messages for the next available session. The receivers 
            also use Session.State to keep track of how much time has been spent processing 
            messages for that session. This state is persisted for the session, so even if a 
            receiver goes down while processing messages in a session (which you can 
            simulate by closing one of the Session Receiver windows) the state will be 
            available to the next receiver that picks up the session.</P>
      <H2 class=heading>Prerequisites</H2>
      <DIV id=sectionSection0 class=section>
        <content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
            If you haven't already done so, please read the release notes
            document that explains how to sign up for a Windows Azure
            account and how to configure your environment.
          </P>
        </content>
      </DIV>
      <H2 class=heading>SampleManager</H2>
      <DIV id=sectionSection1 class="section">
        <content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
              The SampleManager gets user credentials and creates a ServiceBusNamespaceClient 
              (namespaceClient). This entity holds the credentials and is used for all 
              messaging management operations. The namespaceClient is used to create queues 
              for communication between the sender(s) and receiver(s). The SampleManager then 
              creates sender(s) and receiver(s), passing the user credentials to each.</P>
          <p xmlns="">
            The 
              following code prompts for the issuer credentials and then constructs the
            listening URI using that information. The static <code>
              ServiceBusEnvironment.CreateServiceUri
            </code> function is provided to help
            construct the URI with the correct format and domain name. It is strongly
            recommended that you use this function instead of building the URI from scratch
            because the URI construction logic and format might change in future releases.            
            </code>
          </p>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing=0 cellPadding=0 width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD colSpan=2>
                      <PRE>
                        static void Main(string[] args)
                        {
                            // Setup:
                            ParseArgs(args);
                            GetUserCredentials();                        
                            CreateNamespaceClient();

                            // Create queues:
                            Console.WriteLine("Creating Queues...");
                            Queue sessionlessQueue = CreateQueue(false);
                            Console.WriteLine("Created {0}, Queue.RequiresSession = false", sessionlessQueue.Path);
                            Queue sessionQueue = CreateQueue(true);
                            Console.WriteLine("Created {0}, Queue.RequiresSession = true", sessionQueue.Path);

                            ...
                        }

                        static void CreateNamespaceClient()
                        {
                            TransportClientCredentialBase credentials = TransportClientCredentialBase.CreateSharedSecretCredential(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri managementUri = ServiceBusEnvironment.CreateServiceUri("https", ServiceBusNamespace, string.Empty);
                            namespaceClient = new ServiceBusNamespaceClient(managementUri, credentials);
                        }

                        static Queue CreateQueue(bool session)
                        {
                            QueueDescription queueDescription = new QueueDescription() { RequiresSession = session };
                            string queueName = (session ? sessionQueueName : sessionlessQueueName);

                            // Delete the queue if already exists before creation. 
                            if (namespaceManager.QueueExists(queueName))
                            {
                                namespaceManager.DeleteQueue(queueName);
                            }

                            return namespaceClient.CreateQueue(queueName, queueDescription);
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
          <DIV class=code xmlns="">
          </DIV>
          <p xmlns="">
              &nbsp;The SampleManager then creates sender and receiver processes and starts them.<BR>
              <BR>
          </p>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing="0" cellPadding="0" width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD colSpan=2>
                      <PRE class="style1">
                        static void Main(string[] args)
                        {
                            ...

                                    // Start senders and receivers:
                                    Console.WriteLine("\nLaunching senders and receivers...");
                                    StartSenders();
                                    StartReceivers();

                                    Console.WriteLine("\nPress [Enter] to exit.");
                                    Console.ReadLine();

                            ...
                        }

                        private static void StartSenders()
                        {
                            ProcessStartInfo startInfo = new ProcessStartInfo();
                            startInfo.FileName = "SessionMessagesSampleSender.exe";
                            startInfo.Arguments = CreateArgs();
                            for (int i = 0; i < numSenders; ++i)
                            {
                                Process process = Process.Start(startInfo);
                                senderProcs.Add(process);
                            }
                            Thread.Sleep(500);
                            ArrangeWindows();
                        }

                        static void StartReceivers()
                        {
                            ProcessStartInfo startInfo = new ProcessStartInfo();
                            startInfo.FileName = "SessionMessagesSampleReceiver.exe";
                            startInfo.Arguments = CreateArgs();
                            for (int i = 0; i < numReceivers; ++i)
                            {
                                Process process = Process.Start(startInfo);
                                receiverProcs.Add(process);
                            }
                            Thread.Sleep(500);
                            ArrangeWindows();
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
          <P xmlns="">
              Finally, the SampleManager cleans up by deleting the queues and stopping the 
              senders and receivers if necessary.</P>
          <div class="code" xmlns="">
            <span codelanguage="CSharp">
              <table cellpadding="0" cellspacing="0" width="100%">
                <tr>
                  <th>
                    C#&nbsp;
                  </th>
                </tr>
                <tr>
                  <td colspan="2">
                    <pre class="style1">
                    static void Main(string[] args)
                    {
                        ...

                    // Cleanup:
                    namespaceClient.DeleteQueue(sessionlessQueue.Path);
                    namespaceClient.DeleteQueue(sessionQueue.Path);
                    StopSenders();
                    StopReceivers();  
                    }

                    private static void StopSenders()
                    {
                        foreach (Process proc in senderProcs)
                        {
                            proc.CloseMainWindow();
                        }
                    }

                    static void StopReceivers()
                    {
                        foreach (Process proc in receiverProcs)
                        {
                            proc.CloseMainWindow();
                        }
                    }                        
Visual Basic 
                    </pre>
                  </td>
                </tr>
              </table>
            </span>
          </div>
      <H2 class=heading>Sender</H2>
      <DIV id=sectionSection3 class="section">
        <content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
              The sender gets user credentials as parameters from SampleManager and creates a 
              MessagingFactory (messagingFactory). This entity holds the credentials and is 
              used for all messaging runtime operations, such as opening a client to send 
              messages to the queues. The sender then creates a client to the sessionless 
              queue and sends messages.</P>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing=0 cellPadding=0 width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD>
                      <PRE>
                        static void Main(string[] args)
                        {
                            ParseArgs(args);
                            Console.Title = "MessageSender";

                            // Send messages to queue which does not require session
                            QueueClient queueClient = CreateQueueClient(SampleManager.SessionlessQueueName);
                            Console.WriteLine("Preparing to send messages to {0}...", queueClient.Path);
                            Thread.Sleep(3000);

                            SendMessages(queueClient);

                            ...
                        }

                        static void SendMessages(QueueClient queueClient)
                        {
                            // Send messages to queue:
                            Console.WriteLine("Sending messages to queue {0}", queueClient.Path);
                            using (MessageSender sender = queueClient.CreateSender())
                            {
                                System.Random rand = new Random();
                                for (int i = 0; i < SampleManager.NumMessages; ++i)
                                {
                                    string sessionName = rand.Next(SampleManager.NumSessions).ToString();
                                    BrokeredMessage message = CreateSessionMessage(sessionName);
                                    sender.Send(message);
                                    SampleManager.OutputMessageInfo("SEND: ", message);
                                    Thread.Sleep(senderDelay);
                                }
                            }
                            Console.WriteLine();
                        }

                        // Create the runtime entities (queue client)
                        static QueueClient CreateQueueClient(string queueName)
                        {
                            TransportClientCredentialBase credentials = TransportClientCredentialBase.CreateSharedSecretCredential(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb", ServiceBusNamespace, string.Empty);
                            MessagingFactory messagingFactory = MessagingFactory.Create(runtimeUri, credentials);

                            return messagingFactory.CreateQueueClient(queueName);
                        }

                        static BrokeredMessage CreateSessionMessage(string sessionId)
                        {
                            BrokeredMessage message = BrokeredMessage.CreateMessage();
                            message.SessionId = sessionId;
                            message.MessageId = "Order_" + Guid.NewGuid().ToString().Substring(0,5);
                            return message;
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
          <p xmlns="">
              &nbsp;The sender then creates a client to the session queue and sends messages. Note 
              that the messages are created with a SessionId regardless of which queue they 
              are sent to.</p>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing="0" cellPadding="0" width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD>
                      <PRE class="style1">
                        static void Main(string[] args)
                        {
                            ...

                            // Send messages to queue requiring session
                            queueClient = CreateQueueClient(SampleManager.SessionQueueName);
                            Console.WriteLine("Preparing to send messages to {0}...", queueClient.Path);
                            Console.WriteLine("Press [Enter] to begin sending messages.");
                            Console.ReadLine();

                            SendMessages(queueClient);

                            // All messages sent
                            Console.WriteLine("\nSender complete.");
                            Console.ReadLine();
                        }                      
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
        </content>
      </DIV>
        </content>
      </DIV>
      <H2 class=heading>Receiver</H2>
      <DIV id=sectionSection2 class=section>
        <content
xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <P xmlns="">
              The receiver also gets user credentials as parameters from SampleManager and 
              creates a MessagingFactory (messagingFactory). This entity holds the credentials 
              and is used for all messaging runtime operations, such as opening a client to 
              receive messages from the queues. The receiver then creates a client to the 
              sessionless queue and starts receiving messages:</P>
          <DIV class=code xmlns="">
            <SPAN codeLanguage="CSharp">
              <TABLE cellSpacing=0 cellPadding=0 width="100%">
                <TBODY>
                  <TR>
                    <TH>C#&nbsp;</TH>
                  </TR>
                  <TR>
                    <TD colSpan=2>
                      <PRE class="style1">
                        static void Main(string[] args)
                        {
                            ParseArgs(args);
            
                            // Create MessageReceiver for queue which does not require session
                            Console.Title = "MessageReceiver";
                            QueueClient queueClient = CreateQueueClient(SampleManager.SessionlessQueueName);
                            Console.WriteLine("Ready to receive messages from {0}...", queueClient.Path);

                            MessageReceiver receiver = queueClient.CreateReceiver(ReceiveMode.ReceiveAndDelete);
                            lastReceive = DateTime.Now;
                            ReceiveMessages(receiver);
                        
                            ...
                        }

                        static QueueClient CreateQueueClient(string queueName)
                        {
                            TransportClientCredentialBase credentials = TransportClientCredentialBase.CreateSharedSecretCredential(
                                ServiceBusIssuerName, ServiceBusIssuerKey);

                            Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb", ServiceBusNamespace, string.Empty);
                            MessagingFactory messagingFactory = MessagingFactory.Create(runtimeUri, credentials);

                            return messagingFactory.CreateQueueClient(queueName);
                        }

                        static void ReceiveMessages(MessageReceiver receiver)
                        {
                            // Read messages from queue until queue is empty:
                            Console.WriteLine("Reading messages from queue {0}", receiver.Path);
                            Console.WriteLine("Receiver Type: " + receiver.GetType().Name);
            
                            BrokeredMessage receivedMessage;
                            while (receiver.TryReceive(TimeSpan.FromSeconds(receiveMessageTimeout), out receivedMessage))
                            {
                                ProcessMessage(receivedMessage);
                            }

                            receiver.Close();
                        }

                        static void ProcessMessage(BrokeredMessage message, Session session = null)
                        {
                            DateTime startProcessingNewMessage = DateTime.Now;
                            TimeSpan elapsed = startProcessingNewMessage - lastReceive;
                            lastReceive = startProcessingNewMessage;


                            // Using the Session State to track how much processing time was spent on a group.
                            // This value will persist even if a receiver process is killed and the remaining 
                            // messages are picked up by another receiver.
                            string readState = null;
                            if (session != null)
                            {
                                TimeSpan totalElapsed = elapsed;

                                readState = GetState(session);
                                if (readState != null)
                                {
                                    TimeSpan prevElapsed = TimeSpan.FromSeconds(Double.Parse(readState));
                                    totalElapsed = elapsed + prevElapsed;
                                }
                                SetState(session, totalElapsed.TotalSeconds.ToString());                
                            }

                            SampleManager.OutputMessageInfo("RECV: ", message, "State: " + readState);

                            Thread.Sleep(receiverDelay);
                        }
                      </PRE>
                    </TD>
                  </TR>
                </TBODY>
              </TABLE>
            </SPAN>
          </DIV>
        </content>
      </DIV>
      <P xmlns="">
          Once the sessionless queue is empty, the receiver creates a queue client for the 
          session queue and calls AcceptSessionReceiver to begin receiving messages from 
          the first available session. Once all messages from that session have been 
          received, the receiver continues to call AcceptSessionReceiver until there are 
          no sessions of messages remaining.</P>
        <P xmlns="">
            In ProcessMessage, the receiver makes use of the session state to add the 
            processing time for the session each time a message is processed.</P>
      <DIV class=code xmlns="">
        <SPAN codeLanguage="CSharp">
          <TABLE cellSpacing=0 cellPadding=0 width="100%">
            <TBODY>
              <TR>
                <TH>C#&nbsp;</TH>
              </TR>
              <TR>
                <TD colSpan=2>
                  <PRE class="style1">
                    static void Main(string[] args)
                    {
                        ...
                        
                        // Create SessionReceiver for queue requiring session
                        Console.Title = "SessionReceiver";
                        QueueClient sessionQueueClient = CreateQueueClient(SampleManager.SessionQueueName);
                        Console.Clear();
                        Console.WriteLine("Ready to receive messages from {0}...", sessionQueueClient.Path);

                        bool allSessionsAccepted = false;
                        while (!allSessionsAccepted)
                        {
                            try
                            {
                                Console.WriteLine("Checking for session...");
                                SessionReceiver sessionReceiver = sessionQueueClient.AcceptSessionReceiver(ReceiveMode.ReceiveAndDelete, TimeSpan.FromSeconds(acceptSessionReceiverTimeout));
                                ReceiveSessionMessages(sessionReceiver);
                                Console.WriteLine("All received on this session");
                            }
                            catch (TimeoutException)
                            {
                                Console.WriteLine("Got TimeoutException, no more sessions available");
                                allSessionsAccepted = true;
                            }
                        }

                        Console.WriteLine("\nReceiver complete.");
                        Console.ReadLine();
                    }

                    static void ReceiveSessionMessages(SessionReceiver receiver)
                    {
                        // Read messages from queue until queue is empty:
                        Console.WriteLine("Reading messages from queue {0}", receiver.Path);
                        Console.WriteLine("Receiver Type:" + receiver.GetType().Name);
                        Console.WriteLine("Receiver.SessionId = " + receiver.SessionId);

                        BrokeredMessage receivedMessage;
                        while (receiver.TryReceive(TimeSpan.FromSeconds(receiveSessionMessageTimeout), out receivedMessage))
                        {
                            Session session = receiver.Session;
                            ProcessMessage(receivedMessage, session);
                        }

                        receiver.Close();
                    }                    
                    </PRE>
                </TD>
              </TR>
            </TBODY>
          </TABLE>
        </SPAN>
      </DIV>
    </DIV>
    <H2 class=heading>Running the Sample</H2>
    <DIV id=DIV1 class=section>
      <content
xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
        <P xmlns="">
            To run the sample, build the solution in Visual Studio or from the command line, 
            then run the resulting SampleManager.exe executable file. The program will 
            prompt for your service namespace and the issuer credentials. For the 
            issuer secret, be sure to use the &quot;Default Issuer Key&quot; value (typically &quot;owner&quot;) 
            from the portal, rather than one of the management keys.
        </P>
        <P xmlns="">
          <B>Expected Output - SampleManager </B>
        </P>
        <DIV class=code xmlns="">
          <SPAN codeLanguage="other">
            <TABLE cellSpacing=0 cellPadding=0 width="100%">
              <TBODY>
                <TR>
                  <TD>
                    <PRE class="style2">
                         Please provide the namespace to use:
                        &lt;service namespace&gt;
                        Please provide the Issuer name to use:
                        &lt;issuer name&gt;
                        Please provide the Issuer key to use:
                        &lt;issuer key&gt;

                        Creating Queues...
                        Created OrderQueue_NoSession, Queue.RequiresSession = false
                        Created OrderQueue_Session, Queue.RequiresSession = true

                        Launching senders and receivers...

                        Press [Enter] to exit.
                    </PRE>
                  </TD>
                </TR>
              </TBODY>
            </TABLE>
          </SPAN>
        </DIV>
        <P xmlns="">
          <B>Expected Output - Sender</B>
        </P>
        <DIV class=code xmlns="">
          <SPAN codeLanguage="other">
            <TABLE cellSpacing=0 cellPadding=0 width="100%">
              <TBODY>
                <TR>
                  <TD colSpan=2>
                    <PRE class="style2">
                         Preparing to send messages to OrderQueue_NoSession...
                        Sending messages to queue OrderQueue_NoSession
                        SEND: Order_5618c - Group 2.
                        SEND: Order_44753 - Group 0.
                        SEND: Order_de2f7 - Group 0.
                        SEND: Order_d154e - Group 3.
                        ...

                        Preparing to send messages to OrderQueue_Session...
                        Press [Enter] to begin sending messages.

                        Sending messages to queue OrderQueue_Session
                        SEND: Order_f2251 - Group 2.
                        SEND: Order_444c9 - Group 0.
                        SEND: Order_0e7f6 - Group 2.
                        SEND: Order_77c74 - Group 2.
                        ...

                        Sender complete.
                    </PRE>
                  </TD>
                </TR>
              </TBODY>
            </TABLE>
          </SPAN>
        </DIV>
        <P xmlns="">
          <B>Expected Output - Receiver</B>
        </P>
        <DIV class=code xmlns="">
          <SPAN codeLanguage="other">
            <TABLE cellSpacing=0 cellPadding=0 width="100%">
              <TBODY>
                <TR>
                  <TD colSpan=2>
                    <PRE>
                         Ready to receive messages from OrderQueue_NoSession...
                        Reading messages from queue OrderQueue_NoSession
                        Receiver Type: SbmpMessageReceiver
                        RECV: Order_5618c - Group 2. State:
                        RECV: Order_44753 - Group 0. State:
                        RECV: Order_de2f7 - Group 0. State:
                        RECV: Order_d154e - Group 3. State:
                        ...

                        Ready to receive messages from OrderQueue_Session...
                        Checking for session...
                        Reading messages from queue ORDERQUEUE_SESSION
                        Receiver Type:SessionReceiver
                        Receiver.SessionId = 2
                        RECV: Order_f2251 - Group 2. State:
                        RECV: Order_0e7f6 - Group 2. State: 10.3260325
                        RECV: Order_77c74 - Group 2. State: 10.5930267
                        RECV: Order_43a8a - Group 2. State: 10.8810288

                        ...

                        RECV: Order_9d1f6 - Group 3. State: 17.7360284
                        RECV: Order_4d3ec - Group 3. State: 18.0000264
                        RECV: Order_501d2 - Group 3. State: 18.2650265
                        RECV: Order_5668b - Group 3. State: 18.5360271

                        All received on this session
                        Checking for session...
                        Got TimeoutException, no more sessions available

                        Receiver complete.                    
                    </PRE>
                  </TD>
                </TR>
              </TBODY>
            </TABLE>
          </SPAN>
        </DIV>
      </content>
    </DIV>
    <!--[if gte IE 5]><tool:tip avoidmouse="false" element="languageFilterToolTip"></tool:tip><![endif]-->
  </DIV>
  <P xmlns="">
    <hr />
    Did you find this information useful?
    <a href="http://go.microsoft.com/fwlink/?LinkID=155664">
      Please send your suggestions and comments about the documentation.
    </a>
  </P>
  </DIV>
</BODY></HTML>
